package com.lmx.project.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.mail.MailUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lmx.project.annotation.AuthCheck;
import com.lmx.project.common.BaseResponse;
import com.lmx.project.common.ErrorCode;
import com.lmx.project.common.ResultUtils;
import com.lmx.project.exception.BusinessException;
import com.lmx.project.model.dto.users.*;
import com.lmx.project.model.entity.Category;
import com.lmx.project.model.entity.Resourse;
import com.lmx.project.model.entity.Type;
import com.lmx.project.model.entity.Users;
import com.lmx.project.model.vo.UsersVo;
import com.lmx.project.service.CategoryService;
import com.lmx.project.service.ResourseService;
import com.lmx.project.service.TypeService;
import com.lmx.project.service.UsersService;
import com.lmx.project.untils.ExcleUtils;
import com.lmx.project.untils.FileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户接口
 *
 * @author lmx
 */
@RestController
@RequestMapping("/Users")
@Slf4j
@Api("用户模块")
public class UsersController {

    @Resource
    private UsersService usersservice;

    @Resource
    private ResourseService resourseService;

    /**
     * 盐值，混淆密码
     */
    private static final String SALT = "lmx";

//    private String Usersdir = FileUntil.totalpre + "users/";


    private String userpre = "user/";

    private String usersessionpre = "user";
//
//    @Resource
//    private FileUntil fileUntil;

    @Resource
    private FileUtil fileUtil;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private String passcode = "passcode";


    @Resource
    private ExcleUtils excleUtils;

//    @Resource
//    private TypeService typeService;

    @Resource
    private CategoryService categoryService;

    /**
     * 用户注册
     */
    @PostMapping("resgiter")
    @ApiOperation("用户注册")
    public BaseResponse<Boolean> AddUsers(UsersAddRequest usersAddRequest) throws IOException {

        if (!StringUtils.isNotBlank(usersAddRequest.getEmail())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱不能为空");
        }

        if (!StringUtils.isNotBlank(usersAddRequest.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码不能为空");
        }

        if (!StringUtils.isNotBlank(usersAddRequest.getName())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "昵称不能为空");
        }

//        if (usersAddRequest.getAvatar() == null && usersAddRequest.getAddAvatarFile() == null) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR, "头像不能为空");
//        }

        if (!StringUtils.isNotBlank(usersAddRequest.getSchool())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "学校不能为空");
        }

        if (!StringUtils.isNotBlank(usersAddRequest.getGrade())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "年级不能为空");
        }

        if (!StringUtils.isNotBlank(usersAddRequest.getLesson())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "班级不能为空");
        }


        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Users::getEmail, usersAddRequest.getEmail());
        Users one = usersservice.getOne(queryWrapper);
        if (one != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "该邮箱已存在,请勿重复注册");
        }

        Users users = new Users();

        String password = usersAddRequest.getPassword();


        BeanUtils.copyProperties(usersAddRequest, users);
        users.setPermissionlevel(0);
        users.setPassword(
                DigestUtils.md5DigestAsHex(
                        (SALT + password)
                                .getBytes()));
//        if (usersAddRequest.getAddAvatarFile() != null) {
//            MultipartFile addAvatarFile = usersAddRequest.getAddAvatarFile();
//
//
//            String originalFilename = addAvatarFile.getOriginalFilename();
////            后缀名
//            String substring = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
//
//            String resultfilename = UUID.randomUUID().toString().replace("-", "");
//
//
////            String b = fileUtil.saveMultipartFile(addAvatarFile, userpre);
////            if (b != null) {
////                users.setAvatar(b);
////            } else {
////                throw new BusinessException(ErrorCode.PARAMS_ERROR, "图片上传错误");
////            }
//        }

        boolean result = usersservice.save(users);
        return ResultUtils.success(result);
    }


    /**
     * 用户更新
     */
    @PutMapping("update")
    @ApiOperation("用户信息的更新")
    public BaseResponse<Users> UpdateUsers(UsersUpdateRequest updateRequest, HttpServletRequest request) throws IOException {
        final UsersVo userCurrent = usersservice.getUserCurrent(request);
        log.info(updateRequest.toString());
        if (updateRequest.getId() == null || updateRequest.getId() == 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "id属性不能为空");
        }
        log.info("update信息是{}", updateRequest.toString());
//     如果是修改密码，直接加密
//        if (updateRequest.getPassword() != null) {
//            updateRequest.setPassword(
//                    DigestUtils.md5DigestAsHex(
//                            (SALT + updateRequest.getPassword())
//                                    .getBytes()));
//        }
        Users users = new Users();

        BeanUtils.copyProperties(updateRequest, users);

        if (users.getTypedm() != null) {
            if (userCurrent.getTypedm() == null || !userCurrent.getTypedm().equals(users.getTypedm())) {
                Category byId = categoryService.getById(userCurrent.getTypedm());
                if (byId == null) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "组别不存在");
                }
                users.setTypemc(byId.getName());
            }
        }


//        if (updateRequest.getUpdateAvatarFile() != null) {
////            先删除
//            Users byId = usersservice.getById(updateRequest.getId());
//            if (byId == null) {
//                throw new BusinessException(ErrorCode.PARAMS_ERROR, "该用户不存在");
//            }
////            String avatar = byId.getAvatar();
//
////            fileUtil.removeFile(avatar);
//
////            增加新的图像
//            MultipartFile addAvatarFile = updateRequest.getUpdateAvatarFile();
//
////
//            String b = fileUtil.saveMultipartFile(addAvatarFile, userpre);
////            if (b != null) {
////                users.setAvatar(b);
////            } else {
////                throw new BusinessException(ErrorCode.PARAMS_ERROR, "图片上传错误");
////            }
//        }
        log.info("用户信息是{}", users.toString());

        boolean b = usersservice.updateById(users);

//        如果更新成功,写入缓存

        Users one = usersservice.getById(users.getId());
//        普通用户
        if (one.getPermissionlevel().equals(0)) {
            UsersVo usersVo = new UsersVo();
            BeanUtils.copyProperties(one, usersVo);
            log.info("保存到缓存");
            log.info(one.toString());
            HttpSession session = request.getSession();
            session.setAttribute(usersessionpre, usersVo);
            Object attribute = session.getAttribute(usersessionpre);
            log.info("更新后缓存中的内容{}", attribute.toString());
        }

        return ResultUtils.success(one);
    }

    /**
     * 用户登录
     */
    @PostMapping("login")
    @ApiOperation("用户登录")
    public BaseResponse<Users> LoginUsers(@RequestBody UsersLoginRequest UsersLoginRequest, HttpServletRequest request) throws IOException {

        if (!StringUtils.isNotBlank(UsersLoginRequest.getEmail())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱不能为空");
        }

        if (!StringUtils.isNotBlank(UsersLoginRequest.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码不能为空");
        }

        String password = UsersLoginRequest.getPassword();

        String pwd = DigestUtils.md5DigestAsHex((SALT + password).getBytes());

        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Users::getEmail, UsersLoginRequest.getEmail()).eq(Users::getPassword, pwd);
        Users one = usersservice.getOne(queryWrapper);
        UsersVo usersVo = new UsersVo();

//        one.setAvatar(fileUntil.getIpaddress()+one.getAvatar());
        if (one != null) {
            BeanUtils.copyProperties(one, usersVo);
//           如果登录成功，保存到缓存中
            request.getSession().setAttribute(usersessionpre, usersVo);
            return ResultUtils.success(one);
        } else {
            return ResultUtils.error(403, "密码或用户名错误");
        }

    }


    /**
     * 获取当前用户信息
     */
    @GetMapping()
    @ApiOperation("获取当前用户信息")
    public BaseResponse<UsersVo> getUsersByid(HttpServletRequest request) throws IOException {


        UsersVo attribute = usersservice.getUserCurrent(request);


        if (attribute != null) {
//            attribute.setAvatar(preUrl + attribute.getAvatar());
            UsersVo usersVo = new UsersVo();
            BeanUtils.copyProperties(attribute, usersVo);
            return ResultUtils.success(attribute);
        } else {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

    }


    /**
     * 退出登录
     */
    @GetMapping("lought")
    public void lought(HttpServletRequest request) {
        request.getSession().removeAttribute(usersessionpre);
    }


    /**
     * 获取验证码
     */
    @GetMapping("code")
    public BaseResponse<Boolean> getPasscode(HttpServletRequest request) throws IOException {
//        UsersVo usersByid = getUsersByid(request);

        UsersVo data = usersservice.getUserCurrent(request);
//        if (usersByid.getCode() != 0) {
//            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
//        }
//        Users data = usersByid.getData();
        String email = null;
        if (data != null) {
            email = data.getEmail();
        } else {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        Long id = data.getId();
        try {

            String s = RandomUtil.randomNumbers(4);
            log.info("验证码是" + s);
            stringRedisTemplate.opsForValue().set(passcode + ":" + id, s, 5, TimeUnit.MINUTES); //有效时间5分钟
            MailUtil.send(email, "竞赛小组服务平台", "竞赛小组服务平台验证码：" + s + ",该验证码5分钟内有效", false);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }

        return ResultUtils.success(true);
    }

    /**
     * 修改密码的
     */
    @PostMapping("password")
    public BaseResponse<Boolean> updatePassword(@RequestBody UserPasswordRequst userPasswordRequst, HttpServletRequest request) throws IOException {
        log.info(userPasswordRequst.toString());
        if (userPasswordRequst.getNewpassword() == null || userPasswordRequst.getNewpassword().equals("")) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!userPasswordRequst.getNewpassword().equals(userPasswordRequst.getTestpassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次密码不一致");
        }
        if (userPasswordRequst.getPasscode() == null || userPasswordRequst.getPasscode().equals("")) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请输入验证码");
        }

//        获取当前登录用户
//        BaseResponse<Users> usersByid = getUsersByid(request);

        UsersVo data = usersservice.getUserCurrent(request);
//        Users data = usersByid.getData();
        if (data == null) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        Long id = data.getId();

//        验证码是否正确

        String s = stringRedisTemplate.opsForValue().get(passcode + ":" + id);
        if (!userPasswordRequst.getPasscode().equals(s)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码错误");
        }

        Users users = new Users();
        users.setId(id);
        //     如果是修改密码，直接加密
        if (userPasswordRequst.getNewpassword() != null) {
            users.setPassword(
                    DigestUtils.md5DigestAsHex(
                            (SALT + userPasswordRequst.getNewpassword())
                                    .getBytes()));
        }
        boolean b = usersservice.updateById(users);
        if (b) {
            lought(request);
            return ResultUtils.success(b);
        } else {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
    }

    /**
     * 分页查询用户信息
     * TODO 管理员权限调用
     */
    @PostMapping("list")
    @ApiOperation("分页查询用户信息")
    public BaseResponse<Page<UsersVo>> getUsersList(@RequestBody UsersQueryRequest usersQueryRequest) throws IOException {
        if (usersQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Page<UsersVo> usersVoPage = usersservice.getUserVo(usersQueryRequest);
        return ResultUtils.success(usersVoPage);
    }


    /**
     * 根据姓名查找用户信息
     */
    @GetMapping("name")
    public BaseResponse<List<UsersVo>> getUserByname(String name) {
        if (name == null || name.equals("")) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        LambdaQueryWrapper<Users> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Users::getName, name);
        List<Users> list = usersservice.list(queryWrapper);

        String preUrl = fileUtil.getPreUrl();
        List<UsersVo> collect = list.stream().map(users -> {
            UsersVo usersVo = new UsersVo();

            BeanUtils.copyProperties(users, usersVo);

            usersVo.setAvatar(preUrl + usersVo.getAvatar());

            return usersVo;
        }).collect(Collectors.toList());
        return ResultUtils.success(collect);
    }

    /**
     * 获取excle表格模板
     */
    @GetMapping("templete")
//      @AuthCheck(anyAuthority = "school")
    @ApiOperation("获取excle表格模板")
    public ResponseEntity<FileSystemResource> getTemplate() throws IOException {

////        判断数据库中是否存在路径
//        LambdaQueryWrapper<Exclepath> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Exclepath::getType, 2); //2 —— 常见问题
//        Exclepath one = exclepathService.getOne(queryWrapper);
//        String preurl = fileUtil.getPre();
//        if (one != null) {
//
//            return ResultUtils.success(preurl + one.getPath());
//        }
//        如果不存在，创建
        String filename = UUID.randomUUID().toString().replace("-", "");
        List<String> collect = categoryService.list().stream().map(Category::getName).collect(Collectors.toList());
//         获取问题类型
//        List<String> collect = questiontypeService.list().stream().map(Questiontype::getName).collect(Collectors.toList());
//        usce.list().stream().map()
        UserSheetWriteHandler sheetWriteHandler = new UserSheetWriteHandler(collect);
//         设置第一列，问题类别是下拉菜单类型的样式
        String s = excleUtils.CreateTableByContactAndPullDown(UserExcle.class, sheetWriteHandler, filename);

        FileSystemResource file = new FileSystemResource(s);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        String encode = URLEncoder.encode(file.getFilename(), "utf8");

        headers.setContentDispositionFormData("attachment", encode);
        headers.setContentLength(file.contentLength());
//        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
//        客户端可以看到
        ArrayList<String> exposedHeaders = new ArrayList<>();
        exposedHeaders.add("Content-Disposition");
        headers.setAccessControlExposeHeaders(exposedHeaders);
        return new ResponseEntity<>(file, headers, HttpStatus.OK);

    }


    /**
     * 上传表格数据
     */
    @PostMapping("templete")

    @ApiOperation("上传表格数据")
    public BaseResponse<Boolean> addContactExcle(ExcleFileRequest file) throws IOException {
//
        if (file == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        if (file.getFile() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
//        是否是excle表格

        MultipartFile contact = file.getFile();
        boolean b = categoryService.saveUserByExcle(contact);


        return ResultUtils.success(b);


    }

    @DeleteMapping()
    public BaseResponse<Boolean> deleteId(Long id, HttpServletRequest request) {
        UsersVo userCurrent = usersservice.getUserCurrent(request);
        Integer permissionlevel = userCurrent.getPermissionlevel();
        if (permissionlevel == 0) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        boolean b = usersservice.removeById(id);

        if (b) {
            LambdaUpdateWrapper<Resourse> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(Resourse::getUserid, userCurrent.getId()).eq(Resourse::getUserid, id);
            boolean update = resourseService.update(updateWrapper);
            return ResultUtils.success(b);

        } else {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "无此记录");
        }

//        删除后，修改他的资源列表为当前管理员


    }
}
